package com.ruoyi.vote.app.controller;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.config.XytpVoteConfig;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.mall.domain.OrderInfo;
import com.ruoyi.mall.service.OrderInfoService;
import com.ruoyi.mall.util.OrderNoCreate;
import com.ruoyi.vote.app.service.PayService;
import com.ruoyi.vote.common.constants.PayConstants;
import com.ruoyi.vote.common.utils.CreatePayRequestUtil;
import com.ruoyi.weixin.config.CommonConstants;
import com.ruoyi.weixin.config.WxPayConfiguration;
import com.ruoyi.weixin.constant.MyReturnCode;
import com.ruoyi.weixin.utils.LocalDateTimeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * API - 支付接口
 * @author 立勤
 * @date 2023/07/24 17:38:08
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/pay")
@Slf4j
public class ApiPayController {

    private final OrderInfoService orderInfoService;
    private final PayService payService;
    private final XytpVoteConfig xytpVoteConfig;

    /**
     * 订单预支付
     *
     * @param orderInfo 统一下单请求参数
     * @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
     */
    @PostMapping("/unifiedOrder")
    public R<Object> unifiedOrder(@RequestBody OrderInfo orderInfo , HttpServletRequest request) throws WxPayException {
        if(orderInfo.getPaymentPrice().compareTo(BigDecimal.ZERO)==0){//0元购买不调支付
            orderInfo.setPaymentTime(LocalDateTime.now());
            orderInfoService.notifyOrder(orderInfo);
            return R.ok();
        }
        if (payService.orderSub(orderInfo)){
            String body = orderInfo.getName();
            body = body.length() > 40 ? body.substring(0,39) : body;
            String notify = "/api/pay/notify-order";
            WxPayUnifiedOrderRequest orderRequest = CreatePayRequestUtil.createOrderRequest(request, body, notify, orderInfo.getOrderNo(), orderInfo.getPaymentPrice());
            WxPayService wxPayService = WxPayConfiguration.getPayService();
            Object parse = wxPayService.createOrder(orderRequest);
            Map<String,Object> map = new HashMap<>();
            map.put("orderNo",orderInfo.getOrderNo());
            map.put("parse",parse);
            log.info("预支付返回数据: {}",map);
            return R.ok(map);
        }
        return R.fail("订单创建失败");
    }

    /**
     * 支付回调
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @PostMapping("/notify-order")
    public String notifyOrder(@RequestBody String xmlData) throws WxPayException {
        log.info("支付回调:"+xmlData);
        WxPayService wxPayService = WxPayConfiguration.getPayService();
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        OrderInfo orderInfo = orderInfoService.getOne(Wrappers.<OrderInfo>lambdaQuery()
            .eq(OrderInfo::getOrderNo,notifyResult.getOutTradeNo()));
        if(orderInfo != null){
            if(Objects.equals(BaseWxPayRequest.yuanToFen(String.valueOf(orderInfo.getPaymentPrice())), notifyResult.getTotalFee())){
                String timeEnd = notifyResult.getTimeEnd();
                LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd);
                orderInfo.setPaymentTime(paymentTime);
                orderInfo.setTransactionId(notifyResult.getTransactionId());
                payService.notifyOrder(orderInfo);
                return WxPayNotifyResponse.success("成功");
            }else{
                return WxPayNotifyResponse.fail("付款金额与订单金额不等");
            }
        }else{
            return WxPayNotifyResponse.fail("无此订单");
        }
    }
}
